// Learn TypeScript:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/life-cycle-callbacks.html

/**
 * 事件监听器接口
 */
interface EventListener {
    callback: Function;
    target?: any;
    once?: boolean;
}

/**
 * 事件管理器
 * 提供事件的注册、注销、触发等功能
 */
export default class EventManager {
    private static instance: EventManager = null;
    private eventMap: Map<string, EventListener[]> = new Map();

    /**
     * 获取单例实例
     */
    public static getInstance(): EventManager {
        if (!EventManager.instance) {
            EventManager.instance = new EventManager();
        }
        return EventManager.instance;
    }

    /**
     * 注册事件监听器
     * @param eventName 事件名称
     * @param callback 回调函数
     * @param target 回调函数的this指向
     * @param once 是否只执行一次
     */
    public on(eventName: string, callback: Function, target?: any, once: boolean = false): void {
        if (!this.eventMap.has(eventName)) {
            this.eventMap.set(eventName, []);
        }

        const listeners = this.eventMap.get(eventName);
        const listener: EventListener = {
            callback: callback,
            target: target,
            once: once
        };

        listeners.push(listener);
    }

    /**
     * 注册一次性事件监听器
     * @param eventName 事件名称
     * @param callback 回调函数
     * @param target 回调函数的this指向
     */
    public once(eventName: string, callback: Function, target?: any): void {
        this.on(eventName, callback, target, true);
    }

    /**
     * 注销事件监听器
     * @param eventName 事件名称
     * @param callback 回调函数
     * @param target 回调函数的this指向
     */
    public off(eventName: string, callback?: Function, target?: any): void {
        if (!this.eventMap.has(eventName)) {
            return;
        }

        const listeners = this.eventMap.get(eventName);
        
        if (!callback && !target) {
            // 如果没有指定回调和目标，则移除所有该事件的监听器
            this.eventMap.delete(eventName);
            return;
        }

        // 移除匹配的监听器
        for (let i = listeners.length - 1; i >= 0; i--) {
            const listener = listeners[i];
            if ((!callback || listener.callback === callback) && 
                (!target || listener.target === target)) {
                listeners.splice(i, 1);
            }
        }

        // 如果没有监听器了，删除该事件
        if (listeners.length === 0) {
            this.eventMap.delete(eventName);
        }
    }

    /**
     * 触发事件
     * @param eventName 事件名称
     * @param ...args 传递给回调函数的参数
     */
    public emit(eventName: string, ...args: any[]): void {
        if (!this.eventMap.has(eventName)) {
            return;
        }

        const listeners = this.eventMap.get(eventName);
        const onceListeners: EventListener[] = [];

        // 执行所有监听器
        for (let i = 0; i < listeners.length; i++) {
            const listener = listeners[i];
            
            try {
                if (listener.target) {
                    listener.callback.apply(listener.target, args);
                } else {
                    listener.callback(...args);
                }
            } catch (error) {
                console.error(`EventManager: 执行事件 ${eventName} 的回调时出错:`, error);
            }

            // 标记需要移除的一次性监听器
            if (listener.once) {
                onceListeners.push(listener);
            }
        }

        // 移除一次性监听器
        for (const onceListener of onceListeners) {
            this.off(eventName, onceListener.callback, onceListener.target);
        }
    }

    /**
     * 检查是否有指定事件的监听器
     * @param eventName 事件名称
     */
    public hasListener(eventName: string): boolean {
        return this.eventMap.has(eventName) && this.eventMap.get(eventName).length > 0;
    }

    /**
     * 获取指定事件的监听器数量
     * @param eventName 事件名称
     */
    public getListenerCount(eventName: string): number {
        if (!this.eventMap.has(eventName)) {
            return 0;
        }
        return this.eventMap.get(eventName).length;
    }

    /**
     * 清除所有事件监听器
     */
    public clearAll(): void {
        this.eventMap.clear();
    }

    /**
     * 清除指定事件的所有监听器
     * @param eventName 事件名称
     */
    public clearEvent(eventName: string): void {
        this.eventMap.delete(eventName);
    }

    /**
     * 获取所有事件名称
     */
    public getAllEventNames(): string[] {
        return Array.from(this.eventMap.keys());
    }
}

// 导出单例实例，方便使用
export const eventManager = EventManager.getInstance();

// 导出常用的事件名称常量
export const EventNames = {
    // 游戏相关事件
    GAME_START: 'game_start',
    GAME_PAUSE: 'game_pause',
    GAME_RESUME: 'game_resume',
    GAME_OVER: 'game_over',
    GAME_RESTART: 'game_restart',
    
    // 方块相关事件
    BLOCK_SPAWN: 'block_spawn',
    BLOCK_MOVE: 'block_move',
    BLOCK_ROTATE: 'block_rotate',
    BLOCK_LAND: 'block_land',
    LINE_CLEAR: 'line_clear',
    
    // 分数相关事件
    SCORE_CHANGE: 'score_change',
    LEVEL_UP: 'level_up',
    
    // UI相关事件
    UI_SHOW: 'ui_show',
    UI_HIDE: 'ui_hide',
    BUTTON_CLICK: 'button_click'
};
